#include "CircleBuffer.h"
#include "CircularBuffer.h"
#include <iostream>
#include <Windows.h>
#include <time.h>

using namespace std;

#define M_MSG_LEN 300

class CBTest
{
public:
	CBTest(int nBufLen):m_cbBuf(nBufLen){}
	~CBTest(){}

	int Read()
	{
		unsigned char buf[1024];

		int nDataLen = 0;
		unsigned char* pch = (unsigned char*)m_cbBuf.GetBufferStart(nDataLen);
		if (nDataLen > 0)
		{
			nDataLen = (nDataLen > M_MSG_LEN) ? M_MSG_LEN: nDataLen;

			memcpy(buf, pch, nDataLen);
			buf[nDataLen] = '\0';
			m_cbBuf.Remove(nDataLen);

			cout << "Read> len " << nDataLen << " : " << buf << endl;
			return nDataLen;
		}
		else
		{
			cout << "Read> failed, buffer is empty" << endl;

			return 0;
		}

	}

	void Write(char ch)
	{
		int nFreeLen = 0;
		unsigned char* pch = (unsigned char*)m_cbBuf.GetBufferFree(nFreeLen);
		if (nFreeLen > 0)
		{
			nFreeLen = (nFreeLen > M_MSG_LEN) ? M_MSG_LEN: nFreeLen;
			for (int i = 0; i < nFreeLen; i++)
			{
				pch[i] = ch;
			}

			m_cbBuf.Commit(nFreeLen);

			cout << "Write> len = " << nFreeLen << " " << ch << endl;
		}
		else
		{
			cout << "Write fail: buffer is full" << endl;
		}
	}

	void Summar()
	{
		cout << "RemoveCount: " << m_cbBuf.GetRemoveCount() << ", TotalCount: " << m_cbBuf.GetTotalCount()
			<< " -> " << (double)((double)m_cbBuf.GetRemoveCount()/m_cbBuf.GetTotalCount()) << endl;
	}

private:
	CircleBuffer m_cbBuf;
};

class CBTestCLA
{
public:
	CBTestCLA(int nBufLen){
		m_cbBuf.Allocate(nBufLen);
	}
	~CBTestCLA(){}

	int Read()
	{
		unsigned char buf[1024];

		int nDataLen = 0;
		//unsigned char* pch = (unsigned char*)m_cbBuf.GetBufferStart(nDataLen);
		nDataLen = m_cbBuf.GetSize();
		if (nDataLen > 0)
		{
			nDataLen = (nDataLen > M_MSG_LEN) ? M_MSG_LEN: nDataLen;

			//memcpy(buf, pch, nDataLen);
			m_cbBuf.Read(buf, nDataLen);
			buf[nDataLen] = '\0';

			cout << "Read> len " << nDataLen << " : " << buf << endl;
			return nDataLen;
		}
		else
		{
			cout << "Read> failed, buffer is empty" << endl;

			return 0;
		}

	}

	void Write(char ch)
	{
		int nFreeLen = 0;
		//unsigned char* pch = (unsigned char*)m_cbBuf.GetBufferFree(nFreeLen);
		unsigned char pch[M_MSG_LEN+20];
		nFreeLen = m_cbBuf.GetSpace();
		if (nFreeLen > 0)
		{
			nFreeLen = (nFreeLen > M_MSG_LEN) ? M_MSG_LEN: nFreeLen;
			for (int i = 0; i < nFreeLen; i++)
			{
				pch[i] = ch;
			}

			//m_cbBuf.Commit(nFreeLen);
			m_cbBuf.Write(pch, nFreeLen);

			cout << "Write> len = " << nFreeLen << " " << ch << endl;
		}
		else
		{
			cout << "Write fail: buffer is full" << endl;
		}
	}

	void Summar()
	{
		cout << "RemoveCount: " << m_cbBuf.GetRemoveCount() << ", TotalCount: " << m_cbBuf.GetTotalCount()
			<< " -> " << (double)((double)m_cbBuf.GetRemoveCount()/m_cbBuf.GetTotalCount()) << endl;
	}

private:
	CircularBuffer m_cbBuf;
};


int main()
{
	int ch = 0;
	int count = 'a'- 'A';
	CBTestCLA cbTest(2048);
	srand(time(0));

	for (int i = 0; i < 1000; i++)
	{
		ch = i % count;
		ch += 'A';

		for (int j = 0; j < (rand()%30); j++)
		{
			cbTest.Write(ch);
		}

		for (int j = 0; j < (rand()%30); j++)
		{
			cbTest.Read();
		}

		Sleep(10);
	}

	while (cbTest.Read() > 0);

	cbTest.Summar();
	return 0;
}